package com.changyinBus.web.controller.weChartPay.service;

import com.changyinBus.common.utils.uuid.UUID;
import com.changyinBus.web.controller.weChartPay.bean.WeChatPayConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

@Component
@Slf4j
public class WeChatPaySignature {
    @Resource
    private WeChatPayConfig config;

    private PrivateKey privateKey;

    @PostConstruct
    public void init() throws Exception {
        this.privateKey = loadPrivateKey(config.getPrivateKey());
    }

    /**
     * 加载PEM格式的私钥
     */
    private PrivateKey loadPrivateKey(String privateKeyContent) throws Exception {
        // 清理PEM格式的标记
        String privateKeyPEM = privateKeyContent
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s", "");

        byte[] keyBytes = Base64.getDecoder().decode(privateKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 生成随机字符串
     */
    public String generateNonceStr() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
    }

    /**
     * 生成时间戳（秒级）
     */
    public String generateTimestamp() {
        return String.valueOf(System.currentTimeMillis() / 1000);
    }

    /**
     * 构建签名字符串
     */
    public String buildSignMessage(String method, String url, String timestamp,
                                   String nonceStr, String body) {
        // 严格按照微信要求的格式构建
        StringBuilder sb = new StringBuilder();
        sb.append(method).append("\n");
        sb.append(url).append("\n");
        sb.append(timestamp).append("\n");
        sb.append(nonceStr).append("\n");
        sb.append(body).append("\n");

        String signMessage = sb.toString();
        log.debug("签名字符串: {}", signMessage);
        return signMessage;
    }

    /**
     * 对签名字符串进行SHA256-RSA签名
     */
    public String sign(String signMessage) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(signMessage.getBytes(StandardCharsets.UTF_8));

        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }

    /**
     * 生成完整的Authorization头
     */
    public String generateAuthHeader(String method, String url, String body)
            throws Exception {
        String timestamp = generateTimestamp();
        String nonceStr = generateNonceStr();
        System.out.println(url);
        // 构建签名字符串
        String signMessage = buildSignMessage(method, url, timestamp, nonceStr, body);

        // 生成签名
        String signature = sign(signMessage);

        // 构建Authorization头
        String authHeader = String.format(
                "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\",timestamp=\"%s\",serial_no=\"%s\",",
                config.getMchId(), nonceStr, signature, timestamp, config.getMchSerialNo()
        );

        log.debug("生成的Authorization头: {}", authHeader);
        return authHeader;
    }

    /**
     * 验证微信回调签名（重要安全措施）
     */
    public boolean verifySignature(String timestamp, String nonceStr,
                                   String body, String signature,
                                   String serialNo, String wechatPublicKey) {
        try {
            String signMessage = timestamp + "\n" + nonceStr + "\n" + body + "\n";

            Signature verifySignature = Signature.getInstance("SHA256withRSA");
            PublicKey publicKey = loadPublicKey(wechatPublicKey);
            verifySignature.initVerify(publicKey);
            verifySignature.update(signMessage.getBytes(StandardCharsets.UTF_8));

            return verifySignature.verify(Base64.getDecoder().decode(signature));
        } catch (Exception e) {
            log.error("验证微信签名失败", e);
            return false;
        }
    }

    /**
     * 加载微信平台公钥
     */
    private PublicKey loadPublicKey(String publicKeyContent) throws Exception {
        String publicKeyPEM = publicKeyContent
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s", "");

        byte[] keyBytes = Base64.getDecoder().decode(publicKeyPEM);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        return keyFactory.generatePublic(keySpec);
    }
}
